package com.example.springbootshiro.controller.security;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
@Slf4j
public class ShiroConfig {

    @Autowired
    private RedisTemplate redisTemplate;

    @Bean
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        /**
         *  shiro内置过滤器
         *  常用过滤器 :
         *  anon:无需登入 认证考研访问
         *  authc: 必须认证才可以访问
         *  user:如果使用了rememberMe可以直接访问
         *  perms 该资源必须要有资源权限才可以访问
         *  role 必须得到角色权限才可以访问
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
        //filterMap.put("/**", "anon");
        //不能拦截登录接口
        filterMap.put("/shiro/mp/login", "anon");
        filterMap.put("/**", "authc");
        log.info("当前系统拦截模式为:{}", filterMap);
        //设置未授权提示页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/admin/page/noAuth");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        //设置未认证 未登入用户的跳转页面,
        // 前后端不分离jsp情况下,写页面控制器跳转
        // 前后端分离情况下,跳转接口,接口再发送json数据,将页面跳转权利交给前端,只需要协调状态码就行!
        shiroFilterFactoryBean.setLoginUrl("/shiro/mp/nologinCode");//跳转接口 不会被拦截!
        return shiroFilterFactoryBean;
    }

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        //第三部配置自定义sessionId获取方式
        securityManager.setSessionManager(sessionManager());
        //设置权限缓存
        //securityManager.setCacheManager(ehCacheManager);
        return securityManager;
    }

    //第二步 自定义sessionManager
    //@Bean
    //public SessionManager sessionManager() {
    //    DefaultWebSessionManager mySessionManager = new DefaultWebSessionManager();
    //    mySessionManager.setSessionDAO(RedisSessionDAO());
    //    return mySessionManager;
    //}
    @Bean
    public SessionManager sessionManager() {
        MySessionManager mySessionManager = new MySessionManager();
        mySessionManager.setSessionDAO(RedisSessionDAO());
        return mySessionManager;
    }

    @Bean
    public SessionDAO RedisSessionDAO() {
        return new RedisSessionDAO(redisTemplate);
    }


    @Bean(name = "userRealm")
    public UserRealm getRealm() {
        return new UserRealm();
    }

    //@Bean
    //public ShiroDialect getShiroDialect() {
    //    return new ShiroDialect();
    //}
}
